package math2;

import math.FunctionR2ToR;
import math.FunctionRToR;
import math.integration.Integrator1D;
import math.integration.Integrator2D;

/**
 * Integrator for functions.
 */
public class Integrator {

	/**
	 * Integrates the function over the unit cube in n dimension space
	 * 
	 * @param dim
	 *            dimension of space
	 * @param fct
	 *            function define on n dimension
	 * @return the integral
	 */
	public static double integrate(int dim, final FunctionRnToR fct) {
		double tmp = 0;
		/*
		 * integrate 1d
		 */
		if (dim == 1) {
			FunctionRToR f = new FunctionRToR(-1, 1) {

				@Override
				public double valueAt(double x) {
					return fct.valueAt(x);
				}

				@Override
				public int getP() {
					return -1;
				}

				@Override
				public double derivativeAt(double x) {
					return fct.gradientAt(x)[0];
				}
			};
			tmp = Integrator1D.integrate(f);
		}
		/*
		 * integrate 2d
		 */
		else if (dim == 2) {
			FunctionR2ToR f = new FunctionR2ToR() {

				@Override
				public double valueAt(double xi1, double xi2) {
					return fct.valueAt(xi1, xi2);
				}

				@Override
				public double[] gradientAt(double xi1, double xi2) {
					return fct.gradientAt(xi1, xi2);
				}
			};
			tmp = Integrator2D.integrate(f);
		}
		/*
		 * integrate 3d
		 */
		else if (dim == 3) {
			throw new Error(
					"integration for 3 dimension is not implemented yet");
		} else {
			throw new Error(
					"integration for n dimension is not implemented yet");
		}
		return tmp;
	}
}
